#include "Parser.h"
#include "Node.h"
#include "OperatorNode.h"
#include "ValueNode.h"
#include "TreeDraw.h"
#include <stack>
using namespace parser;

Parser::Parser()
:root_(NULL){
}

Parser::~Parser()
{
}

operatorNode::OperatorNode::OperatorType IsOperator(std::string::const_iterator& pos)
{
	if (*pos == '+'){
		return operatorNode::OperatorNode::ot_add;
	}else if (*pos == '-'){
		return operatorNode::OperatorNode::ot_sub;
	}else if (*pos == '*'){
		return operatorNode::OperatorNode::ot_mul;
	}else if (*pos == '/'){
		return operatorNode::OperatorNode::ot_div;
	}
	return operatorNode::OperatorNode::ot_none;
}

int OperatorWeight(operatorNode::OperatorNode* n){
	switch (n->Type()){
		case operatorNode::OperatorNode::ot_add:
		case operatorNode::OperatorNode::ot_sub:
			return 1;
			break;
		case operatorNode::OperatorNode::ot_mul:
		case operatorNode::OperatorNode::ot_div:
			return 2;
			break;

	}

	return -1;
}

node::Node* Parser::Process(std::string::const_iterator start, std::string::const_iterator end, node::Node* parent)
{	
	std::string::const_iterator last = start;
	//operatorNode::OperatorNode::OperatorType lastop = operatorNode::OperatorNode::ot_none;
	operatorNode::OperatorNode * lastop = NULL;
	operatorNode::OperatorNode * current = NULL;
	//node::Node * current = NULL;
	node::Node * root = NULL;

	std::string::const_iterator it = start;
	while(true){
		operatorNode::OperatorNode::OperatorType op = operatorNode::OperatorNode::ot_none;

		if (it != end)
			op = IsOperator(it);
		if (op == operatorNode::OperatorNode::ot_none && it != end){
			++it;
			continue;
		}
		
		node::Node * val = new valueNode::ValueNode(std::string(last, it));

		operatorNode::OperatorNode * oper = NULL;

		if (it != end)
			oper = new operatorNode::OperatorNode(op);

		if (lastop == NULL){
			lastop = oper;
		}

		if (root == NULL)
			root = oper;


		val->Parent(lastop);		
		if (lastop->Left() == NULL)
			lastop->Left(val);
		else{
			lastop->Right(val);	
			//current = val;
		}
		if (oper != NULL && lastop != oper){			
			if (OperatorWeight(lastop) >= OperatorWeight(oper)){	
				while (lastop->Parent() != NULL && lastop->Type()>= oper->Type())
					lastop = (operatorNode::OperatorNode*)lastop->Parent();

				lastop->Parent(oper);
				oper->Left(lastop);				
				//root = oper;
				lastop = oper;
			}else{
				oper->Parent(val->Parent());
				val->Parent(oper);				
				oper->Left(val);

				if (lastop->Left() == NULL)
					lastop->Left(oper);
				else
					lastop->Right(oper);

				lastop = oper;
			}
		}
	
		if (it == end)
			break;

		last = ++it;
	}

	while (root->Parent() != NULL)
		root = root->Parent();

	return root;
}

bool Parser::Parse(const std::string& buffer)
{

	root_ = Process(buffer.begin(), buffer.end(), NULL);
	DrawTree(root_);	
	return root_ != NULL;
}


